<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>18-js的原型和原型链</title>
  </head>
  <body>
    <script>
      //====>> 原型
      class Stundent {
        constructor(name, score) {
          // super(name);
          this.name = name;
          this.score = score;
        }

        study() {
          console.log(`我是${this.name},我在学习。。。`);
        }
        say() {}
      }

      const stu = new Stundent("张三", 85);
      console.log(stu);
      console.log(Stundent.prototype);
      console.log(Stundent.__proto__);
      /**
       * stu是 Student类的实例对象。
       * stu对象中有一个属性 __proto__。这个__proto__属性就是 stu 对象的隐式原型
       *
       * 类Student有一个 prototype。Student.prototype 是 显示原型
       */
      console.log(Stundent.prototype === stu.__proto__); // ===> true 。说明是指向同同一个对象
      /**
       * 类实例化的对象中的 __proto__ 指向的就是 类的 prototype
       * 类中的 方法 都在类的 prototype属性对象中
       * 实列对象 中没有 study 方法。他就会去 __proto__属性中找(指向的类的 prototype )。
       */

      // let obj = { a: 12 };
      // let temp = JSON.parse(JSON.stringify(obj));
      // console.log(obj === temp);

      //=====>>原型链
      class Animal {
        constructor(color) {
          this.color = color;
        }
        eat() {
          console.log("我是动物，我是" + this.color + "色的");
        }
      }
      class Dog extends Animal {
        constructor(color, height) {
          super(color);
          this.height = height;
        }

        run() {
          cosnole.log("我是狗，我会跑步");
        }
      }
      let dog = new Dog("白", 20);
      console.log(dog);
      console.log(dog.__proto__);
      console.log(Dog.prototype);
      console.log(Dog.prototype.__proto__);
      console.log(Animal.prototype);
      // console.log(Dog.__proto__)
      console.log(dog.hasOwnProperty("color")); //判断属性是否是自身的

      /**
       * 类 Dog 继承了 类 Animal
       * dog 是通过 类 Dog 构造出来的实列对象
       * Dog.eat() 为什么可以正常执行呢？ (eat 方法 是类 Animal 中的方法)
       * dog的 原型__proto__ 指向 类 Dog 的原型 prototype
       * 因为 Dog 类 继承了 Animal 类
       * 所以类 Dog 的 prototype 显示原型 下也有 __proto__隐式原型 指向 类 Animal 的 prototype 显示原型
       * dog.__proto__ ----> Dog.prototype  Dog.prototype.__proto__ -----> Animal.prototype
       *                     Dog原型中有run 方法                           Animal原型有 edt 方法
       * 所以这就形成了原型链
       * dog.run 可以执行。因为 run方法 在dog对象中没有找到，所以它会去dog.__proto__中找，能找到就能执行
       * dog.eat 可以执行。因为 eat方法 在dog对象自身中没有找到，dog.__proto__也没有找到，然后就去 dog.__proto__.__proto__可以找到。一层一层往__proto__属性中找
       */
    </script>
  </body>
</html>
